
package com.joysuch.wwyt.bp.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.zlg.common.util.CollectionUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.joysuch.wwyt.bp.bean.BpTargetExamineRecordBean;
import com.joysuch.wwyt.bp.bean.tagert.*;
import com.joysuch.wwyt.bp.entity.BpDepart;
import com.joysuch.wwyt.bp.entity.BpJob;
import com.joysuch.wwyt.bp.entity.target.BpTargetDuty;
import com.joysuch.wwyt.bp.entity.target.BpTargetExamineRecord;
import com.joysuch.wwyt.bp.enums.AssessmentResults;
import com.joysuch.wwyt.bp.enums.AssessmentResults;
import com.joysuch.wwyt.bp.enums.DataStateTypes;
import com.joysuch.wwyt.bp.enums.TargetDutyTypes;
import com.joysuch.wwyt.bp.mapper.BpTargetDutyMapper;
import com.joysuch.wwyt.bp.repository.BpDepartDao;
import com.joysuch.wwyt.bp.repository.BpJobDao;
import com.joysuch.wwyt.bp.repository.BpTargetDutyDao;
import com.joysuch.wwyt.bp.repository.BpTargetExamineRecordDao;
import com.joysuch.wwyt.bp.service.BpTargetDutyService;
import com.joysuch.wwyt.common.constant.Constant;
import com.joysuch.wwyt.core.bean.BaseAttachmentBean;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.common.util.PageDataUtils;
import com.joysuch.wwyt.core.entity.BaseUser;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.core.service.BaseRoleDataAuthService;
import com.joysuch.wwyt.core.service.BizCodeGeneratorFacade;
import com.joysuch.wwyt.core.support.Context;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.util.Assert;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class BpTargetDutyServiceImpl implements BpTargetDutyService {

    @Autowired
    private BpTargetDutyDao dao;
    @Autowired
    private BizCodeGeneratorFacade bizCodeGeneratorFacade;
    @Autowired
    private BaseUserDao baseUserDao;
    @Autowired
    private BpDepartDao bpDepartDao;
    @Autowired
    private BpJobDao bpJobDao;
    @Autowired
    private BpTargetExamineRecordDao recordDao;
    @Autowired
    private BpTargetDutyMapper bpTargetDutyMapper;

    @Resource
    private BaseRoleDataAuthService baseRoleDataAuthService;

    @Override
    public ResultBean save(BpTargetDutyBean bean) {
        Long id = bean.getId();
        String title = bean.getTitle();
        List<BpTargetNormBean> targetNormList = bean.getTargetNormList();
        BpTargetDuty duty;
        if (id == null) {
            Integer titleCount = dao.countByTitle(title);
            if (titleCount != null) {
                return ResultBean.fail(101, "此标题已存在");
            }
            duty = new BpTargetDuty();
            duty.setCode(bizCodeGeneratorFacade.mubiaozeren());
            duty.setStatus(TargetDutyTypes.COMPILE.getIndex());
            duty.setState(DataStateTypes.EFFECTIVE.getState());
        } else {
            duty = getDutyById(id);
            if (DataStateTypes.UN_EFFECTIVE.getState().equals(duty.getState())) {
                return ResultBean.fail(101, "此数据已作废");
            }
            //审核通过后即不可修改
//            if (duty.getStatus() >= TargetDutyTypes.AUDIT_PASS.getIndex()) {
//                return ResultBean.fail(101, "审核通过后不可修改");
//            }
            if (!title.equals(duty.getTitle())) {
                Integer integer = dao.countByTitle(title);
                if (integer != null) {
                    return ResultBean.fail(101, "此标题已存在");
                }
            }
        }
        //验证完成期限
        Assert.isTrue(auditFinishLimit(bean), "完成期限不符合要求");
        BeanUtils.copyProperties(bean, duty);
        BaseAttachmentBean attachment = bean.getAttachment();
        duty.setAttachment(attachment == null ? null : JSON.toJSONString(attachment));
        //目标指标
        duty.setTargetNormJson(CollectionUtils.isEmpty(targetNormList) ? null : JSON.toJSONString(targetNormList));
        List<String> dutyObject = bean.getDutyObject();
        if (CollectionUtils.isNotEmpty(dutyObject)) {
            String dutyObjectStr = dutyObject.stream().collect(Collectors.joining(Constant.SPLIT_COMMA));
            duty.setDutyObject(dutyObjectStr);
        }
        BpTargetDuty save = dao.save(duty);
        return ResultBean.success(save.getId());
    }

    /**
     * 验证完成期限  false: 验证不通过
     * 周期类型 0 年度目标; 1 季度目标; 2 月度目标
     * 循环制定 0 循环; 1 单次
     */
    private boolean auditFinishLimit(BpTargetDutyBean bean) {
        Byte periodType = bean.getPeriodType();
        Byte repeatOrSingle = bean.getRepeatOrSingle();
        String finishLimit = bean.getFinishLimit();
        try {
            //年份需要大于等于当前年
            Integer year = getYearByFinishLimit(finishLimit);
            int nowYear = LocalDate.now().getYear();
            if (year < nowYear) {
                return false;
            }
            int yearIndex = finishLimit.indexOf("年");
            if (repeatOrSingle == 0) {
                if (!finishLimit.contains("年") || finishLimit.length() != 5) {
                    return false;
                }
            } else {
                if (periodType == 0) {
                    if (!finishLimit.contains("年") || finishLimit.length() != 5) {
                        return false;
                    }
                } else if (periodType == 1) {
                    if (!(finishLimit.contains("年") && finishLimit.contains("季度"))) {
                        return false;
                    }
                    int quarterIndex = finishLimit.indexOf("季度");
                    Integer.parseInt(finishLimit.substring(yearIndex + 1, quarterIndex));
                } else if (periodType == 2) {
                    if (!(finishLimit.contains("年") && finishLimit.contains("月"))) {
                        return false;
                    }
                    int monthIndex = finishLimit.indexOf("月");
                    Integer.parseInt(finishLimit.substring(yearIndex + 1, monthIndex));
                }
            }
        } catch (NumberFormatException e) {
            return false;
        }
        return true;
    }

    @Override
    public ResultBean get(Long id) {
        BpTargetDuty duty = getDutyById(id);
        BpTargetDutyDto dto = new BpTargetDutyDto();
        BeanUtils.copyProperties(duty, dto);
        String targetNormJson = duty.getTargetNormJson();
        dto.setTargetNormList(targetNormJson == null ? null : JSON.parseArray(targetNormJson, BpTargetNormBean.class));
        String attachment = duty.getAttachment();
        dto.setAttachment(attachment == null ? null : JSONObject.parseObject(duty.getAttachment(), BaseAttachmentBean.class));
        //责任对象
        Byte normLevel = duty.getNormLevel();
        String dutyObject = duty.getDutyObject();
        if (duty.getNormLevel() != null && duty.getNormLevel() == 2 && duty.getParentId() != null) {
            setUserObjectName(duty, dto);
        } else {
            dto.setDutyObjectName(getObjectName(normLevel, dutyObject));
        }
        List<String> dutyObjectList = Arrays.asList(dutyObject.split(","));
        dto.setDutyObject(dutyObjectList);
        Long markUserId = duty.getMarkUserId();
        dto.setMarkUserName(markUserId == null ? "" : baseUserDao.getBaseUserNameById(duty.getMarkUserId()));
        Long markDepartId = duty.getMarkDepartId();
        dto.setMarkDepartName(markDepartId == null ? "" : bpDepartDao.getNameById(duty.getMarkDepartId()));
        return ResultBean.success(dto);
    }

    private String getObjectName(Byte normLevel, String dutyObject) {
        String dutyObjectName = null;
        if (normLevel == 0) {
            dutyObjectName = dutyObject;
        } else if (normLevel == 1) {
            List<Long> longs = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(dutyObject).stream().map(Long::new).collect(Collectors.toList());
            dutyObjectName = bpDepartDao.findByIdInFO(longs).stream().map(BpDepart::getName).collect(Collectors.joining(Constant.SPLIT_COMMA));
        } else if (normLevel == 2) {
            List<Long> longs = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(dutyObject).stream().map(Long::new).collect(Collectors.toList());
            String collect = bpJobDao.findAllByIdInfo(longs).stream().map(BpJob::getName).collect(Collectors.joining(Constant.SPLIT_COMMA));
            dutyObjectName = collect;
        } else if (normLevel == 4) { //车间级
            List<Long> longs = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(dutyObject).stream().map(Long::new).collect(Collectors.toList());
            dutyObjectName = bpDepartDao.findByIdInFO(longs).stream().map(BpDepart::getName).collect(Collectors.joining(Constant.SPLIT_COMMA));
        }
        return dutyObjectName;
    }

    @Override
    public ResultBean delete(Long id) {
        Assert.notNull(id, "id cannot be null");
        BpTargetDuty duty = getDutyById(id);
        if (DataStateTypes.UN_EFFECTIVE.getState().equals(duty.getState())) {
            return ResultBean.fail(101, "此数据已作废");
        }
//        if (duty.getStatus() >= TargetDutyTypes.AUDIT_PASS.getIndex()) {
//            return ResultBean.fail(101, "审核通过后不可删除");
//        }
        dao.nullify(id);
        return ResultBean.defaultSuccessResult();
    }

    @Override
    public int deleteMark(Long id) {
        return bpTargetDutyMapper.deleteMark(id);
    }

    @Override
    public ResultBean submitAudit(Long id) {
        Assert.notNull(id, "id cannot be null");
        BpTargetDuty duty = getDutyById(id);
        if (DataStateTypes.UN_EFFECTIVE.getState().equals(duty.getState())) {
            return ResultBean.fail(101, "此数据已作废");
        }
        Byte status = duty.getStatus();
        if (!TargetDutyTypes.COMPILE.getIndex().equals(status)
                && !TargetDutyTypes.AUDIT_FAIL.getIndex().equals(status)) {
            return ResultBean.fail(101, "此状态不可提交审核");
        }
        duty.setStatus(TargetDutyTypes.WAIT_AUDIT.getIndex());
        dao.save(duty);
        return ResultBean.defaultSuccessResult();
    }

    @Override
    public ResultBean audit(Long id, Integer flag) {
        Assert.notNull(id, "id cannot be null");
        BpTargetDuty duty = getDutyById(id);
        if (DataStateTypes.UN_EFFECTIVE.getState().equals(duty.getState())) {
            return ResultBean.fail(101, "此数据已作废");
        }
        Byte status = duty.getStatus();
        if (!TargetDutyTypes.WAIT_AUDIT.getIndex().equals(status)) {
            return ResultBean.fail(101, "此状态不可审核");
        }
        duty.setStatus(flag == 0 ? TargetDutyTypes.AUDIT_FAIL.getIndex() : TargetDutyTypes.AUDIT_PASS.getIndex());
        if (flag == 1) {
            //审核通过，计划即不可修改，同时生成待考核记录
            List<BpTargetExamineRecord> recordList = getExamineRecordList(duty);
            recordDao.saveAll(recordList);
        }
        dao.save(duty);
        return ResultBean.defaultSuccessResult();
    }

    /**
     * 生成待考核记录
     * 周期类型 0 年度目标; 1 季度目标; 2 月度目标
     * 循环制定 0 循环; 1 单次
     */
    private List<BpTargetExamineRecord> getExamineRecordList(BpTargetDuty duty) {
        List<BpTargetExamineRecord> recordList = Lists.newArrayList();
        Long dutyId = duty.getId();
        Byte periodType = duty.getPeriodType();
        Byte repeatOrSingle = duty.getRepeatOrSingle();
        String finishLimit = duty.getFinishLimit();
        Byte normLevel = duty.getNormLevel();
        //岗位级需要分发给岗位下所有人
        //生成多个duty
        List<BpTargetDuty> targetDutyList = null;
        if(normLevel == 1){
            String dutyObject = duty.getDutyObject();
            List<Long> longs = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(dutyObject).stream().map(Long::new).collect(Collectors.toList());
            List<BpTargetDuty> needList = Lists.newArrayList();
            if(CollectionUtils.isNotEmpty(longs)){
                for(Long longList : longs){
                    BpTargetDuty targetDuty = new BpTargetDuty();
                    BeanUtils.copyProperties(duty, targetDuty);
                    targetDuty.setId(null);
                    targetDuty.setParentId(dutyId);
                    targetDuty.setDutyObject(String.valueOf(longList));
                    needList.add(targetDuty);
                }
                targetDutyList = dao.saveAll(needList);
            }
        }
        if (normLevel == 2) {
            String dutyObject = duty.getDutyObject();
            List<Long> longs = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(dutyObject).stream().map(Long::new).collect(Collectors.toList());
            List<Long> userIds = baseUserDao.findIdByJobIn(longs);
            if (CollectionUtils.isNotEmpty(userIds)) {
                List<BpTargetDuty> needList = Lists.newArrayList();
                for (Long userId : userIds) {
                    BpTargetDuty targetDuty = new BpTargetDuty();
                    BeanUtils.copyProperties(duty, targetDuty);
                    targetDuty.setId(null);
                    targetDuty.setParentId(dutyId);
                    targetDuty.setDutyObject(String.valueOf(userId));
                    needList.add(targetDuty);
                }
                targetDutyList = dao.saveAll(needList);
            }
        }
        if (normLevel == 4) {
            String dutyObject = duty.getDutyObject();
            List<Long> longs = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(dutyObject).stream().map(Long::new).collect(Collectors.toList());
            List<BpTargetDuty> needList = Lists.newArrayList();
            if(CollectionUtils.isNotEmpty(longs)){
                for(Long longList : longs){
                    BpTargetDuty targetDuty = new BpTargetDuty();
                    BeanUtils.copyProperties(duty, targetDuty);
                    targetDuty.setId(null);
                    targetDuty.setParentId(dutyId);
                    targetDuty.setDutyObject(String.valueOf(longList));
                    needList.add(targetDuty);
                }
                targetDutyList = dao.saveAll(needList);
            }
        }

        //单次生成一条记录
        if (repeatOrSingle == 1 || (repeatOrSingle == 0 && periodType == 0)) {
            if (targetDutyList != null) {
                for (BpTargetDuty bpTargetDuty : targetDutyList) {
                    BpTargetExamineRecord record = new BpTargetExamineRecord();
                    record.setDutyId(bpTargetDuty.getId());
                    record.setFinishLimit(finishLimit);
                    recordList.add(record);
                }
            } else {
                BpTargetExamineRecord record = new BpTargetExamineRecord();
                record.setDutyId(dutyId);
                record.setFinishLimit(finishLimit);
                recordList.add(record);
            }
        } else {
            //季度
            if (periodType == 1) {
                if (targetDutyList != null) {
                    for (BpTargetDuty bpTargetDuty : targetDutyList) {
                        for (int i = 1; i <= 4; i++) {
                            BpTargetExamineRecord record = new BpTargetExamineRecord();
                            record.setDutyId(bpTargetDuty.getId());
                            record.setFinishLimit(finishLimit + i + "季度");
                            recordList.add(record);
                        }
                    }
                } else {
                    for (int i = 1; i <= 4; i++) {
                        BpTargetExamineRecord record = new BpTargetExamineRecord();
                        record.setDutyId(dutyId);
                        record.setFinishLimit(finishLimit + i + "季度");
                        recordList.add(record);
                    }
                }
            }
            //月
            else if (periodType == 2) {
                if (targetDutyList != null) {
                    for (BpTargetDuty bpTargetDuty : targetDutyList) {
                        for (int i = 1; i <= 12; i++) {
                            BpTargetExamineRecord record = new BpTargetExamineRecord();
                            record.setDutyId(bpTargetDuty.getId());
                            record.setFinishLimit(finishLimit + i + "月");
                            recordList.add(record);
                        }
                    }
                } else {
                    for (int i = 1; i <= 12; i++) {
                        BpTargetExamineRecord record = new BpTargetExamineRecord();
                        record.setDutyId(dutyId);
                        record.setFinishLimit(finishLimit + i + "月");
                        recordList.add(record);
                    }
                }
            }
        }
        recordList.forEach(r -> r.setStatus(TargetDutyTypes.EXAMINE_UNDO.getType()));
        return recordList;
    }

    /**
     * 获取月份所在季度
     */
    private int getNowQuarter(int nowMonth) {
        if (nowMonth <= 3) {
            return 1;
        } else if (nowMonth <= 6) {
            return 2;
        } else if (nowMonth <= 9) {
            return 3;
        }
        return 4;
    }

    private Integer getYearByFinishLimit(String finishLimit) {
        return Integer.parseInt(finishLimit.substring(0, finishLimit.indexOf("年")));
    }

    //flag: 0 制定; 1 审核; 2 考核
    @Override
    public ResultBean pageType(Pageable pageable, BpTargetQueryBean bean) {
        pageable = PageDataUtils.addOrderByDesc(pageable, "id");
        bean.setOrgCode(Context.getCompanyCode());
        bean.setTenentId(Context.getCurrentTenantId());
        Byte normLevel = bean.getNormLevel();
        Byte periodType = bean.getPeriodType();
        Byte flag = bean.getFlag();
        List<Long> currAuthDepartIds = baseRoleDataAuthService.findDepartIdsByCurUser();
        // 无数据权限，直接返回
        if (CollectionUtil.isEmpty(currAuthDepartIds)) {
            return ResultBean.success(new ArrayList<>());
        }
        List<String> departIdStrList = currAuthDepartIds.stream().map(Object::toString).collect(Collectors.toList());
        bean.setDepartIds(departIdStrList);
        List<BpTargetPageDto> dtoList = new ArrayList<>();
        Page<BpTargetDuty> page = null;
        if(flag == 0){
            Page<BpTargetDuty> bpTargetDutyPage = new Page<>(pageable.getPageNumber() + 1,pageable.getPageSize());
            buildParam(bean,currAuthDepartIds);
             page = bpTargetDutyMapper.selectByMake(bpTargetDutyPage, bean);
            for (BpTargetDuty duty : page.getRecords()) {
                BpTargetPageDto dto = new BpTargetPageDto();
                BeanUtils.copyProperties(duty, dto);
                if (flag == 1 || flag == 0) {
                    dto.setStatusName(getStatusName(duty.getStatus()));
                } else {
                    dto.setStatusName(getStatusNameStr(duty.getStatus()));
                }
                //责任对象
                if (duty.getNormLevel() != null && duty.getNormLevel() == 2 && duty.getParentId() != null) {
                    setUserObjectName(duty, dto);
                } else {
                    String dutyList = duty.getDutyObject();
                    dto.setDutyObjectName(getObjectName(duty.getNormLevel(), dutyList));
                }

                dtoList.add(dto);
            }
        } else if (flag == 1){
            String auditState = bean.getAuditState();
            if (auditState != null) {
                Byte status = TargetDutyTypes.getIndexByType(auditState);
                ArrayList<Byte> list = new ArrayList<>();
                if (TargetDutyTypes.AUDIT_PASS.getIndex().equals(status)) {
                    list.add(TargetDutyTypes.AUDIT_PASS.getIndex());
                    list.add(TargetDutyTypes.EXAMINE_UNDO.getIndex());
                    list.add(TargetDutyTypes.EXAMINE_DONE.getIndex());
                    list.add(TargetDutyTypes.EXAMINE_DOING.getIndex());
                } else if (TargetDutyTypes.WAIT_AUDIT.getIndex().equals(status)) {
                    list.add(TargetDutyTypes.WAIT_AUDIT.getIndex());
                } else if (TargetDutyTypes.AUDIT_FAIL.getIndex().equals(status)) {
                    list.add(TargetDutyTypes.AUDIT_FAIL.getIndex());
                }
                bean.setData(list);
            } else {
                ArrayList<Byte> list = new ArrayList<>();
                list.add(TargetDutyTypes.WAIT_AUDIT.getIndex());
                list.add(TargetDutyTypes.AUDIT_FAIL.getIndex());
                list.add(TargetDutyTypes.AUDIT_PASS.getIndex());
                list.add(TargetDutyTypes.EXAMINE_UNDO.getIndex());
                list.add(TargetDutyTypes.EXAMINE_DONE.getIndex());
                list.add(TargetDutyTypes.EXAMINE_DOING.getIndex());
                bean.setData(list);
            }
            Page<BpTargetDuty> bpTargetDutyPage = new Page<>(pageable.getPageNumber() + 1,pageable.getPageSize());
            buildParam(bean,currAuthDepartIds);
            page = bpTargetDutyMapper.selectByAudit(bpTargetDutyPage, bean);
            for (BpTargetDuty duty : page.getRecords()) {
                BpTargetPageDto dto = new BpTargetPageDto();
                BeanUtils.copyProperties(duty, dto);
                if (flag == 1 || flag == 0) {
                    dto.setStatusName(getStatusName(duty.getStatus()));
                } else {
                    dto.setStatusName(getStatusNameStr(duty.getStatus()));
                }
                //责任对象
                if (duty.getNormLevel() != null && duty.getNormLevel() == 2 && duty.getParentId() != null) {
                    setUserObjectName(duty, dto);
                } else {
                    String dutyList = duty.getDutyObject();
                    dto.setDutyObjectName(getObjectName(duty.getNormLevel(), dutyList));
                }
                dtoList.add(dto);
            }
        } else if(flag ==2){
            if(bean.getExamineState()!=null && bean.getExamineState().equals(TargetDutyTypes.EXAMINE_UNDO.getType())){
                bean.setStatus(TargetDutyTypes.AUDIT_PASS.getIndex());
            }else if(bean.getExamineState()!=null && bean.getExamineState().equals(TargetDutyTypes.EXAMINE_DOING.getType())){
                bean.setStatus(TargetDutyTypes.EXAMINE_DOING.getIndex());
            }else if(bean.getExamineState()!=null && bean.getExamineState().equals(TargetDutyTypes.EXAMINE_DONE.getType())){
                bean.setStatus(TargetDutyTypes.EXAMINE_DONE.getIndex());
            }
            ArrayList<Byte> list = new ArrayList<>();
                    list.add(TargetDutyTypes.AUDIT_PASS.getIndex());
                    list.add(TargetDutyTypes.EXAMINE_UNDO.getIndex());
                    list.add(TargetDutyTypes.EXAMINE_DONE.getIndex());
                    list.add(TargetDutyTypes.EXAMINE_DOING.getIndex());
                    bean.setData(list);
            Page<BpTargetDuty> bpTargetDutyPage = new Page<>(pageable.getPageNumber() + 1,pageable.getPageSize());
            buildParam(bean,currAuthDepartIds);
           page = bpTargetDutyMapper.selectByCheck(bpTargetDutyPage, bean);
            for (BpTargetDuty duty : page.getRecords()) {
                BpTargetPageDto dto = new BpTargetPageDto();
                BeanUtils.copyProperties(duty, dto);
                if (flag == 1 || flag == 0) {
                    dto.setStatusName(getStatusName(duty.getStatus()));
                } else {
                    dto.setStatusName(getStatusNameStr(duty.getStatus()));
                }
                //责任对象
                if (duty.getNormLevel() != null && duty.getNormLevel() == 2 && duty.getParentId() != null) {
                    setUserObjectName(duty, dto);
                } else {
                    String dutyList = duty.getDutyObject();
                    dto.setDutyObjectName(getObjectName(duty.getNormLevel(), dutyList));
                }
                dtoList.add(dto);
            }
        }
        return ResultBean.pageData(dtoList,page.getTotal()) ;
    }


    //flag: 0 制定; 1 审核; 2 考核
    @Override
    public ResultBean page(Pageable pageable, BpTargetQueryBean bean) {
        pageable = PageDataUtils.addOrderByDesc(pageable, "id");
        Byte normLevel = bean.getNormLevel();
        Byte periodType = bean.getPeriodType();
        Byte flag = bean.getFlag();
        Specification<BpTargetDuty> specification = (Root<BpTargetDuty> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (normLevel != null) {
                predicates.add(cb.equal(root.get("normLevel"), normLevel));
            }
            if (periodType != null) {
                predicates.add(cb.equal(root.get("periodType"), periodType));
            }
            predicates.add(cb.equal(root.get("state"), 1));
            if (flag == 1) {
                //过滤duty子项
                predicates.add(cb.isNull(root.get("parentId")));
                String auditState = bean.getAuditState();
                if (auditState != null) {
                    Byte status = TargetDutyTypes.getIndexByType(auditState);
                    List<Byte> list = Lists.newArrayList();
                    if (TargetDutyTypes.AUDIT_PASS.getIndex().equals(status)) {
                        list.add(TargetDutyTypes.AUDIT_PASS.getIndex());
                        list.add(TargetDutyTypes.EXAMINE_UNDO.getIndex());
                        list.add(TargetDutyTypes.EXAMINE_DONE.getIndex());
                        list.add(TargetDutyTypes.EXAMINE_DOING.getIndex());
                    } else if (TargetDutyTypes.WAIT_AUDIT.getIndex().equals(status)) {
                        list.add(TargetDutyTypes.WAIT_AUDIT.getIndex());
                    } else if (TargetDutyTypes.AUDIT_FAIL.getIndex().equals(status)) {
                        list.add(TargetDutyTypes.AUDIT_FAIL.getIndex());
                    }
                    addInCondition(root, cb, predicates, list);
                } else {
                    List<Byte> list = Lists.newArrayList();
                    list.add(TargetDutyTypes.WAIT_AUDIT.getIndex());
                    list.add(TargetDutyTypes.AUDIT_FAIL.getIndex());
                    list.add(TargetDutyTypes.AUDIT_PASS.getIndex());
                    list.add(TargetDutyTypes.EXAMINE_UNDO.getIndex());
                    list.add(TargetDutyTypes.EXAMINE_DONE.getIndex());
                    list.add(TargetDutyTypes.EXAMINE_DOING.getIndex());
                    addInCondition(root, cb, predicates, list);
                }
            } else if (flag == 2) {
                String examineState = bean.getExamineState();
                if (examineState != null) {
                    if (TargetDutyTypes.EXAMINE_UNDO.getType().equals(examineState)) {
                        List<Byte> list = Lists.newArrayList();
                        list.add(TargetDutyTypes.AUDIT_PASS.getIndex());
                        list.add(TargetDutyTypes.EXAMINE_UNDO.getIndex());
                        addInCondition(root, cb, predicates, list);
                    } else if (TargetDutyTypes.EXAMINE_DONE.getType().equals(examineState)) {
                        predicates.add(cb.equal(root.get("status"), TargetDutyTypes.EXAMINE_DONE.getIndex()));
                    } else if (TargetDutyTypes.EXAMINE_DOING.getType().equals(examineState)) {
                        predicates.add(cb.equal(root.get("status"), TargetDutyTypes.EXAMINE_DOING.getIndex()));
                    }
                } else {
                    List<Byte> list = Lists.newArrayList();
                    list.add(TargetDutyTypes.AUDIT_PASS.getIndex());
                    list.add(TargetDutyTypes.EXAMINE_UNDO.getIndex());
                    list.add(TargetDutyTypes.EXAMINE_DONE.getIndex());
                    list.add(TargetDutyTypes.EXAMINE_DOING.getIndex());
                    addInCondition(root, cb, predicates, list);
                }
                //过滤岗位级 父项
                Predicate parentId = cb.isNull(root.get("parentId"));
                Predicate normLevel1 = cb.equal(root.get("normLevel"), 2);
                Predicate parentIdNotNull = cb.isNotNull(root.get("parentId"));
                Predicate normLevelNotEqual = cb.notEqual(root.get("normLevel"), 2);
                Predicate one = cb.and(parentIdNotNull, normLevel1);
                Predicate two = cb.and(parentId, normLevelNotEqual);
                Predicate or = cb.or(one, two);
                predicates.add(or);
            } else {
                predicates.add(cb.isNull(root.get("parentId")));
            }
            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };
        List<BpTargetPageDto> dtoList = Lists.newArrayList();
        org.springframework.data.domain.Page<BpTargetDuty> page = dao.findAll(specification, pageable);
        for (BpTargetDuty duty : page) {
            BpTargetPageDto dto = new BpTargetPageDto();
            BeanUtils.copyProperties(duty, dto);
            if (flag == 1 || flag == 0) {
                dto.setStatusName(getStatusName(duty.getStatus()));
            } else {
                dto.setStatusName(getStatusNameStr(duty.getStatus()));
            }
            //责任对象
            if (duty.getNormLevel() != null && duty.getNormLevel() == 2 && duty.getParentId() != null) {
                setUserObjectName(duty, dto);
            } else {
                dto.setDutyObjectName(getObjectName(duty.getNormLevel(), duty.getDutyObject()));
            }
            dtoList.add(dto);
        }
        return ResultBean.pageData(dtoList, page.getTotalElements());
    }

    private void buildParam(BpTargetQueryBean bean,List<Long> currAuthDepartIds) {
        String dutyObjectName = bean.getDutyObjectName();
        if (StringUtils.isEmpty(dutyObjectName)) {
            return;
        }
        List<Long> departIds = bpDepartDao.findIdByNameLike(dutyObjectName);
        if (CollectionUtils.isNotEmpty(departIds)) {
            List<Long> departIdList = departIds.stream().filter(currAuthDepartIds::contains).collect(Collectors.toList());
            List<String> departIdStrList = departIdList.stream().map(e -> e.toString()).collect(Collectors.toList());
            bean.setDepartIds(departIdStrList);
        } else {
            bean.setDepartIds(Lists.newArrayList());
        }
        List<BpJob> jobs = bpJobDao.findByNameLike(dutyObjectName);
        if (CollectionUtils.isNotEmpty(jobs)) {
            List<String> jobIds = jobs.stream().map(BpJob::getId).map(e -> e.toString()).collect(Collectors.toList());
            bean.setJobIds(jobIds);
        }
        List<Long> userId =baseUserDao.getNameByIds(dutyObjectName);
        if(CollectionUtils.isNotEmpty(userId)){
            List<String> userIdList = userId.stream().map(e -> e.toString()).collect(Collectors.toList());
            bean.setUserIds(userIdList);
        }
    }

    public static void main(String[] args) {
        List<Integer> list1 = new ArrayList<>();
        list1.add(1);
        list1.add(2);
        list1.add(3);
        list1.add(4);
        List<Integer> list2 = new ArrayList<>();
        list2.add(3);
        list2.add(4);
        list2.add(5);
        list2.add(6);
        list2.add(1);
        List<Integer> list = list2.stream().filter(list1::contains).collect(Collectors.toList());
        System.out.println(list);
    }

    private void setUserObjectName(BpTargetDuty duty, BpTargetDto dto) {
        Long parentId = duty.getParentId();
        BpTargetDuty parent = dao.getOne(parentId);
        String dutyObject= parent.getDutyObject();
        List<Long> longs = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(dutyObject).stream().map(Long::new).collect(Collectors.toList());
        String collect = bpJobDao.findAllByIds(longs).stream().map(BpJob::getName).collect(Collectors.joining(Constant.SPLIT_COMMA));
        dto.setDutyObjectName(getObjectName(duty, collect));
    }

    private String getObjectName(BpTargetDuty duty, String jobName) {
        String userId = duty.getDutyObject();

        List<Long> longs = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(userId).stream().map(Long::new).collect(Collectors.toList());
        String userName ="";
        String jobNames = "";

            Optional<BaseUser> obu = baseUserDao.findById(longs.get(0));
            if (obu.isPresent()){
                BaseUser baseUser = obu.get();
                userName=baseUser.getRealName();
                Optional<BpJob> obj = bpJobDao.findById(baseUser.getJob());
                if (obj.isPresent()){
                    BpJob bpJob = obj.get();
                    jobNames=bpJob.getName();
                }
            }

        if (userName == null || jobNames == null) {
            return "";
        }
        return userName + "(" + jobNames + ")";
    }



    private void addInCondition(Root<BpTargetDuty> root, CriteriaBuilder cb, List<Predicate> predicates, List<Byte> list) {
        CriteriaBuilder.In<Object> in = cb.in(root.get("status"));
        for (Byte b : list) {
            in.value(b);
        }
        predicates.add(in);
    }

    @Override
    public ResultBean examineRecord(Long id, Integer flag) {
        Assert.notNull(id, "id cannot be null");
        List<BpTargetExamineRecordBean> beans=new ArrayList<>();
        List<BpTargetExamineRecord> list = recordDao.findByDutyIdAndStatus(id, flag == 0 ?
                TargetDutyTypes.EXAMINE_UNDO.getType() : TargetDutyTypes.EXAMINE_DONE.getType());
        List<Long> userIds = list.stream().map(r -> r.getExamineUserId()).collect(Collectors.toList());
        Map<Long, String> toolMap = baseUserDao.findAllById(userIds).stream().collect(Collectors.toMap(BaseUser::getId, BaseUser::getRealName));
        for (BpTargetExamineRecord record : list) {
            record.setExamineUserName(toolMap.get(record.getExamineUserId()));
            BpTargetExamineRecordBean bean = new BpTargetExamineRecordBean();
            BeanUtils.copyProperties(record,bean);
            if (org.apache.commons.lang3.StringUtils.isNotBlank(record.getExamineResult())) {
                bean.setExamineResult(AssessmentResults.getNameByCode(record.getExamineResult()));
            }
            beans.add(bean);
        }
        return ResultBean.success(beans);
    }

    @Override
    public ResultBean examineStart(Long recordId) {
        Assert.notNull(recordId, "id cannot be null");
        BpTargetExamineRecord record = getRecordById(recordId);
        if (TargetDutyTypes.EXAMINE_DONE.getType().equals(record.getStatus())) {
            return ResultBean.fail(101, "当前记录已考核过");
        }
        BpTargetDutyDto dutyDto = (BpTargetDutyDto) get(record.getDutyId()).getData();
        dutyDto.setFinishLimit(record.getFinishLimit());
        return ResultBean.success(dutyDto);
    }

    @Override
    public ResultBean examineSubmit(BpTargetExamineBean bean) {
        Long recordId = bean.getRecordId();
        BpTargetExamineRecord record = getRecordById(recordId);
        String status = record.getStatus();
        Long dutyId = record.getDutyId();
        if (TargetDutyTypes.EXAMINE_DONE.getType().equals(status)) {
            return ResultBean.fail(101, "此记录已考核过");
        }
        record.setExamineDate(bean.getExamineDate());
        record.setTotalScores(bean.getTotalScores());
        record.setExamineUserId(bean.getExamineUserId());
        if (org.apache.commons.lang3.StringUtils.isNotBlank(bean.getExamineResult())) {
            record.setExamineResult(AssessmentResults.getCodeByName(bean.getExamineResult()));
        }
        record.setStatus(TargetDutyTypes.EXAMINE_DONE.getType());
        List<BpTargetNormResultBean> resultBeanList = bean.getResultBeanList();
        if (CollectionUtils.isEmpty(resultBeanList)) {
            record.setNormFinishDetail(null);
        } else {
            record.setNormFinishDetail(JSON.toJSONString(resultBeanList));
        }
        recordDao.save(record);
        //检查当前dutyId对应的记录是否全部已考核
        int count = recordDao.countByDutyIdAndStatus(dutyId, TargetDutyTypes.EXAMINE_UNDO.getType());
        if (count == 0) {
            dao.examineSet(dutyId, TargetDutyTypes.EXAMINE_DONE.getIndex());
        } else {
            dao.examineSet(dutyId, TargetDutyTypes.EXAMINE_DOING.getIndex());
        }
        return ResultBean.defaultSuccessResult();
    }

    @Override
    public ResultBean examineRecordDetail(Long recordId) {
        Assert.notNull(recordId, "id cannot be null");
        BpTargetExamineRecord record = getRecordById(recordId);
        BpTargetDutyDto dutyDto = (BpTargetDutyDto) get(record.getDutyId()).getData();
        dutyDto.setFinishLimit(record.getFinishLimit());
        dutyDto.setTotalScores(record.getTotalScores());
        dutyDto.setTargetNormList(null);
        BpTargetRecordDto recordDto = new BpTargetRecordDto();
        recordDto.setExamineDate(record.getExamineDate());
        recordDto.setExamineResult(AssessmentResults.getNameByCode(record.getExamineResult()));
        Long examineUserId = record.getExamineUserId();
        recordDto.setExamineUserId(examineUserId);
        recordDto.setExamineUserName(baseUserDao.getBaseUserNameById(examineUserId));
        recordDto.setDutyDto(dutyDto);

        String normFinishDetail = record.getNormFinishDetail();
        recordDto.setResultBeanList(normFinishDetail == null ? null : JSON.parseArray(normFinishDetail, BpTargetNormResultBean.class));
        return ResultBean.success(recordDto);
    }

    private BpTargetExamineRecord getRecordById(Long recordId) {
        return recordDao.findById(recordId).orElseThrow(() -> new IllegalArgumentException("此数据不存在"));
    }

    //考核页，审核通过-显示未考核
    private String getStatusNameStr(Byte status) {
        if (TargetDutyTypes.AUDIT_PASS.getIndex().equals(status)) {
            return TargetDutyTypes.EXAMINE_UNDO.getType();
        } else {
            return TargetDutyTypes.getTypeByIndex(status);
        }
    }

    //编制，审核页  未考核&已考核-显示审核通过
    private String getStatusName(Byte status) {
        if (status >= TargetDutyTypes.EXAMINE_DONE.getIndex()) {
            return TargetDutyTypes.AUDIT_PASS.getType();
        } else {
            return TargetDutyTypes.getTypeByIndex(status);
        }
    }

    private BpTargetDuty getDutyById(Long id) {
        return dao.findById(id).orElseThrow(() -> new IllegalArgumentException("此数据不存在"));
    }
}
